<?php

namespace app\common\service\logistics;

use app\common\library\ApiException;
use app\common\model\ExpressCfg;
use app\common\model\ExpressComment;
use app\common\model\ExpressCooperate;
use app\common\model\ExpressOrder;
use app\common\model\ExpressUser;
use app\common\model\TerminalOrder;
use think\Db;
use think\Exception;
use think\Request;

/**
 * 订单管理
 */
class Order
{


    /**
     * 配置信息
     */
    public function cfg()
    {
        return ExpressCfg::find();
    }

    /**
     * 快递公司列表
     */
    public function kd_list()
    {
        return Db::name("express_delivery")->where("status",1)->select();
    }

    /**
     * 发布寄件订单
     * @param $auth
     * @param Request $request
     * @return string
     * @throws ApiException
     */
    public function sending($auth,Request $request)
    {
        $request->filter(['strip_tags']);
        //取件地址
        $sending_id   = $request->param("sending_id");
        //收件地址
        $receiving_id = $request->param("receiving_id");
        if(!$sending_id || !$receiving_id){
            throw new ApiException("请选择寄件或者取件地址");
        }
        if($receiving_id == $sending_id){
            throw new ApiException("请勿选择相同地址");
        }
        //快递公司
        $express_name = $request->param("express_name");
        if(!$express_name){
            throw new ApiException("请选择快递公司");
        }

        $obj = new \MapApi();
        //取件位置
        $address_location = explode(",",\app\common\model\Address::where("id",$sending_id)->value("location"));

        //用户选择快递员
        $express_id   = $request->param("express_id");
        $rob_time     = 0;
        if($express_id){
            $express_info = ExpressUser::where("eu.id",$express_id)
                ->alias('eu')
                ->join("terminal_express te","te.express_id=eu.id")
                ->field("eu.id,eu.work_type,eu.user_id,eu.username,te.gettime,eu.status")//快递员ID、状态、用户ID,名称、最新轨迹时间、接单状态
                ->find();
            if(!$express_info || $express_info["work_type"] == 0){
                throw new ApiException("快递员不存在或休息中");
            }

            /**获取快递员轨迹**/
            $r = $obj->search_track($express_info["user_id"]."_".$express_info["id"],$express_info["gettime"],$express_info["gettime"]+86400);
            if($r["status"] != 0 || $r["message"] != "OK"){
                throw new ApiException("获取快递员位置信息失败");
            }
            $track_list = $r["result"]["track"];
            $last_track = end($track_list);
            if(!$last_track){
                throw new ApiException("获取快递员位置信息失败");
            }
            //判断快递员最新位置是否在取件地址范围内 -3km
            $range_num = distance($address_location[0],$address_location[1],$last_track["lat"],$last_track["lng"]);
            if($range_num > "3"){
                throw new ApiException("快递员位置不在当前范围内");
            }
            $rob_time = time();
            /**end**/
        }

        //期待上门时间
        $start_door_time = $request->param("start_door_time");
        $end_door_time   = $request->param("end_door_time");
        if(!$start_door_time || !$end_door_time){
            throw new ApiException("请选择上门时间");
        }

        //物品重量+级别
        $goods_level     = $request->param("goods_level");
        $goods_weight    = $request->param("goods_weight");
        if(!$goods_level || !$goods_weight){
            throw new ApiException("请选择物品重量+级别");
        }

        //运费预算
        $cfg = $this->cfg();
        $total_price     = $cfg["price"] * bcmul($goods_weight,$cfg["continuous_price"],2);
        //快递员佣金
        $cfg = config('site');
        $charge          = bcmul($total_price,$cfg["express_charge"],2);
        $express_price   = bcsub($total_price,$charge,2);
        Db::startTrans();
        try {
            $res = ExpressOrder::create([
                "order_no"          => $auth->id,
                "receiving_id"      => $receiving_id,
                "sending_id"        => $sending_id,
                "express_name"      => $express_name,
                "express_uid"       => $express_id,
                "user_id"           => $auth->id,
                "start_door_time"   => $start_door_time,
                "end_door_time"     => $end_door_time,
                "goods_level"       => $goods_level,
                "goods_weight"      => $goods_weight,
                "goods_status"      => $express_id?1:0,//未选择快递员默认待接单,选择快递员状态未待取件
                "total_price"       => $total_price,
                "rob_time"          => $rob_time,
                "express_price"     => $express_price,
                "fee_price"         => $charge,
            ]);
            if(!$res){
                throw new Exception("创建订单失败了");
            }
            //添加一个包裹的终端
            TerminalOrder::create([
                "user_id"   => $auth->id,
                "order_id"  => $res->id,
                "gettime"   => time(),
                "location"  => implode(",",$address_location),
                "lat"       => $address_location[0],
                "lnt"       => $address_location[1],
            ]);
            $entity_id = $auth->id."|".$res->id;
            $terminal_status = 0;
            //默认选择了快递员,修改终端
            if($express_id){
                $terminal_status = 1;
            }
            //创建包裹终端-修改状态
            $order_r = $obj->create_terminal($entity_id,$res->id,"order","包裹-".$res->id,"",$terminal_status);
            if($order_r["status"] !=0 || $order_r["message"] != 'OK'){
                throw new Exception($order_r["message"]);
            }

            //上传位置
            $order_r_track = $obj->create_track($entity_id,$address_location[0],$address_location[1]);
            if($order_r_track["status"] !=0 || $order_r_track["message"] != 'OK'){
                throw new Exception($order_r_track["message"]);
            }
            Db::commit();
            return "下单成功";
        }catch (Exception $e){
            Db::rollback();
            throw new ApiException($e->getMessage());
        }
    }

    /**
     * 快递员接单
     * @param $auth
     * @param $oid
     * @return string
     */
    public function rob($auth,$oid)
    {
        $express_user = ExpressUser::where("user_id",$auth->id)->find();
        if(!$express_user){
            throw new ApiException("您不是快递员");
        }

        Db::startTrans();
        try {
            $order = ExpressOrder::where("id",$oid)
                ->lock(true)
                ->find();
            if(!$order || $order["goods_status"] != 0){
                throw new Exception("订单不存在或已被接单");
            }
            $r = $order->save([
                "express_uid"    => $express_user->id,
                "goods_status"  => 1,
                "rob_time"      => time()
            ]);
            if(!$r){
                throw new Exception("接单失败了");
            }
            #修改包裹终端状态
            $obj = new \MapApi();
            $res_order = $obj->update_terminal($order->user_id."|".$order->id,"包裹-".$order->id,"包裹被接单",1);
            if($res_order["status"] !=0 || $res_order["message"] != 'OK'){
                throw new Exception($res_order["message"]);
            }
            #修改快递员终端状态
            $res_user = $obj->update_terminal($express_user->user_id."_".$express_user->id,$express_user->username,"接单",1);
            if($res_user["status"] !=0 || $res_user["message"] != 'OK'){
                throw new Exception($res_user["message"]);
            }
            Db::commit();
            return "接单成功,请按时取件哦";
        }catch (Exception $e){
            Db::rollback();
            throw new Exception($e->getMessage());
        }
    }

    /**
     * 快递员取件
     * @param $auth
     * @param $oid
     * @return string
     */
    public function picked($auth,$oid)
    {
        $express_user = ExpressUser::where("user_id",$auth->id)->find();
        if(!$express_user){
            throw new ApiException("您不是快递员");
        }
        $order = ExpressOrder::where("id",$oid)
            ->where("express_uid",$express_user->id)
            ->find();
        if(!$order || $order["goods_status"] != 1){
            throw new ApiException("订单不存在或已取件");
        }
        Db::startTrans();
        try {
            $r = $order->save([
                "goods_status"  => 2,
                "picked_time"   => time(),
            ]);
            if(!$r){
                throw new Exception("操作失败");
            }
            Db::commit();
            return "操作成功";
        }catch (Exception $e){
            Db::rollback();
            throw new ApiException($e->getMessage());
        }
    }

    /**
     * 快递员完成订单
     * @param $auth
     * @param $oid
     * @return string
     */
    public function finish($auth,Request $request)
    {
        $request->filter(['strip_tags']);
        $oid            = $request->param("oid");
        $express_img    = $request->param("express_img","");
        $express_no     = $request->param("express_no");
        /*if( !$express_no){
            throw new ApiException("请上传快递单号和图");
        }*/
        $express_user = ExpressUser::where("user_id",$auth->id)->find();
        if(!$express_user){
            throw new ApiException("您不是快递员");
        }
        $order = ExpressOrder::where("id",$oid)
            ->where("express_uid",$express_user->id)
            ->find();
        if(!$order || $order["goods_status"] != 2){
            throw new ApiException("订单不存在或已完成");
        }
        Db::startTrans();
        try {
            $r = $order->save([
                "goods_status" => 3,
                "finish_time"  => time(),
                "express_img"  => $express_img,
                "express_no"   => $express_no,
            ]);
            if(!$r){
                throw new Exception("操作失败");
            }
            #完成订单奖励佣金
            $reward = $order["total_price"];
            $res1 = ExpressUser::setMoney($auth->id,$express_user->id,$reward,"完成订单奖励",[
                "order_money"   => bcadd($express_user["order_money"],$reward,2),
                "order_num"     => bcadd($express_user["order_num"],1),
                "status"        => 0
            ],"order",$oid);
            if($res1 !== true){
                throw new Exception($res1);
            }
            #添加合作记录
            ExpressCooperate::setAdd($order->user_id,$express_user->id);
            #修改终端快递员状态
            $obj = new \MapApi();
            #删除订单包裹终端
            $del_order = $obj->delete_terminal($order->user_id."|".$order->id);
            if($del_order["status"] !=0 || $del_order["message"] != 'OK'){
                throw new Exception($del_order["message"]);
            }
            Db::commit();
            return "操作成功";
        }catch (Exception $e){
            Db::rollback();
            throw new ApiException($e->getMessage());
        }
    }

    /**
     * 快递员订单
     * @param $auth
     * @param Request $request
     */
    public function express_list($auth,Request $request){

        $request->filter(['strip_tags']);
        if($auth->express_type != 1){
            throw new ApiException("您不是快递员身份");
        }
        $express_user = ExpressUser::where("user_id",$auth->id)->field("id")->find();
        $status = $request->param("goods_status");
        $where  = [];
        if($status != "all"){
            $where["goods_status"] = $status;
        }
        $list =   ExpressOrder::alias("o")
            ->join("address a1","a1.id=o.sending_id")
            ->join("address a2","a2.id=o.receiving_id")
            ->where("express_uid",$express_user->id)
            ->where($where)
            ->field("o.id as oid,goods_status,receiving_id,sending_id,start_door_time,end_door_time,o.picked_time,o.finish_time,o.rob_time")
            ->field("a1.name as a1name,a1.mobile as a1mobile,a1.area_address as a1areaaddress,a1.name_address as a1name_address,a1.door_number as a1doornumber")
            ->field("a2.name as a2name,a2.mobile as a2mobile,a2.area_address as a2areaaddress,a2.name_address as a2name_address,a2.door_number as a2doornumber")
            ->order("o.id desc")
            ->paginate($request->param("limit",15));
        $today = date("Ymd",time());
        foreach($list as $l){
            //查询期望上门时间
            $door_time = strtotime($l["end_door_time"]) - time();
            if($door_time <= 60*30){
                $l->door_str = "30分钟之内";
            }else if($door_time <= 60*60*2){
                $l->door_str = "2小时之内";
            }else{
                $door_date = date("Ymd",strtotime($l["end_door_time"]));
                $door_time = explode(" ",$l["start_door_time"])[1]."~".explode(" ",$l["end_door_time"])[1];
                if($today == $door_date){
                    $l->door_str = "今天:".$door_time;
                }else if($door_date == date("Ymd",strtotime("+1 day"))){
                    $l->door_str = "明天:".$door_time;
                }else if($door_date == date("Ymd",strtotime("+2 day"))){
                    $l->door_str = "后天:".$door_time;
                }
            }
            if($l["rob_time"]){
                $l->rob_time = date("Y-m-d H:i:s",$l["rob_time"]);
            }
            if($l["picked_time"]){
                $l->picked_time = date("Y-m-d H:i:s",$l["picked_time"]);
            }
            if($l["finish_time"]){
                $l->finish_time = date("Y-m-d H:i:s",$l["finish_time"]);
            }
        }
        return $list;
    }

    /**
     * 快递员订单详情
     * @param $oid
     */
    public function express_detail($uid,$oid)
    {
        $express_user = ExpressUser::where("user_id",$uid)->field("id")->find();
        if(!$express_user){
            throw new ApiException("您不是快递员身份");
        }
        $where["o.id"] = $oid;
        $info =    ExpressOrder::alias("o")
            ->join("address a1","a1.id=o.sending_id")
            ->join("address a2","a2.id=o.receiving_id")
            ->where("express_uid",$express_user->id)
            ->where($where)
            ->field("o.id as oid,goods_status,receiving_id,sending_id,start_door_time,end_door_time,order_no,goods_type,goods_weight,total_price,pay_status,o.rob_time,o.picked_time,o.finish_time")
            ->field("a1.name as a1name,a1.mobile as a1mobile,a1.area_address as a1areaaddress,a1.name_address as a1name_address,a1.door_number as a1doornumber,a1.location as a1location")
            ->field("a2.name as a2name,a2.mobile as a2mobile,a2.area_address as a2areaaddress,a2.name_address as a2name_address,a2.door_number as a2doornumber,a2.location as a2location")
            ->find();

        $today = date("Ymd",time());
        $door_time = strtotime($info["end_door_time"]) - time();
        if($door_time <= 60*30){
            $info->door_str = "30分钟之内";
        }else if($door_time <= 60*60*2){
            $info->door_str = "2小时之内";
        }else{
            $door_date = date("Ymd",strtotime($info["end_door_time"]));
            $door_time = explode(" ",$info["start_door_time"])[1]."~".explode(" ",$info["end_door_time"])[1];
            if($today == $door_date){
                $info->door_str = "今天:".$door_time;
            }else if($door_date == date("Ymd",strtotime("+1 day"))){
                $info->door_str = "明天:".$door_time;
            }else if($door_date == date("Ymd",strtotime("+2 day"))){
                $info->door_str = "后天:".$door_time;
            }
        }
        if($info["rob_time"]){
            $info->rob_time = date("Y-m-d H:i:s",$info["rob_time"]);
        }
        if($info["picked_time"]){
            $info->picked_time = date("Y-m-d H:i:s",$info["picked_time"]);
        }
        if($info["finish_time"]){
            $info->finish_time = date("Y-m-d H:i:s",$info["finish_time"]);
        }
        return $info;
    }

    /**
     * 用户订单
     * @param $auth
     * @param Request $request
     */
    public function user_list($auth,Request $request){
        $request->filter(['strip_tags']);
        $status = $request->param("goods_status");
        $where  = [];
        if($status != "all"){
            $where["goods_status"] = $status;
        }
        $list =   ExpressOrder::alias("o")
            ->join("address a1","a1.id=o.sending_id")
            ->join("address a2","a2.id=o.receiving_id")
            ->where("o.user_id",$auth->id)
            ->where($where)
            ->field("o.id as oid,goods_status,receiving_id,sending_id,start_door_time,end_door_time,o.createtime,o.express_uid")
            ->field("a1.name as a1name,a1.mobile as a1mobile,a1.area_address as a1areaaddress,a1.name_address as a1name_address,a1.door_number as a1doornumber,a1.location as a1location")
            ->field("a2.name as a2name,a2.mobile as a2mobile,a2.area_address as a2areaaddress,a2.name_address as a2name_address,a2.door_number as a2doornumber,a2.location as a2location")
            ->order("o.id desc")
            ->paginate($request->param("limit",15));
        $currentTime = time(); // 获取当前时间的时间戳
        foreach($list as $l){
            $createTime = $l->createtime; // 获取创建时间的时间戳

            $timeDiff = $currentTime - $createTime; // 计算时间差（单位：秒）

            $pay_str = "";
            $days = floor($timeDiff / (60 * 60 * 24)); // 计算天数
            if($days > 0){
                $pay_str = sprintf("%s天",$days);
            }
            $hours = floor(($timeDiff % (60 * 60 * 24)) / (60 * 60)); // 计算小时数
            if($hours > 0){
                $pay_str .= sprintf("%s时",$hours);
            }
            $minutes = floor(($timeDiff % (60 * 60)) / 60); // 计算分钟数
            if($minutes > 0){
                $pay_str .= sprintf("%s分",$minutes);
            }
            $seconds = $timeDiff % 60; // 计算秒数
            if($seconds > 0){
                $pay_str .= sprintf("%s秒",$seconds);
            }
            $l->pay_str=  $pay_str;
            $l->express_user = (new Express())->express_user_info(null,$l->express_uid);
        }
        return $list;
    }

    /**
     * 用户订单详情
     * @param $oid
     */
    public function user_detail($uid=null,$oid)
    {
        $where["o.id"] = $oid;
        $info =    ExpressOrder::alias("o")
            ->join("address a1","a1.id=o.sending_id")
            ->join("address a2","a2.id=o.receiving_id")
            ->where($where)
            ->field("o.id as oid,goods_status,receiving_id,sending_id,start_door_time,end_door_time,order_no,goods_type,goods_weight,total_price,pay_status,o.createtime,o.express_uid")
            ->field("a1.name as a1name,a1.mobile as a1mobile,a1.area_address as a1areaaddress,a1.name_address as a1name_address,a1.door_number as a1doornumber,a1.location as a1location")
            ->field("a2.name as a2name,a2.mobile as a2mobile,a2.area_address as a2areaaddress,a2.name_address as a2name_address,a2.door_number as a2doornumber,a2.location as a2location")
            ->find();

        $currentTime = time(); // 获取当前时间的时间戳
        $createTime = $info->createtime; // 获取创建时间的时间戳

        $timeDiff = $currentTime - $createTime; // 计算时间差（单位：秒）

        $pay_str = "";
        $days = floor($timeDiff / (60 * 60 * 24)); // 计算天数
        if($days > 0){
            $pay_str = sprintf("%s天",$days);
        }
        $hours = floor(($timeDiff % (60 * 60 * 24)) / (60 * 60)); // 计算小时数
        if($hours > 0){
            $pay_str .= sprintf("%s时",$hours);
        }
        $minutes = floor(($timeDiff % (60 * 60)) / 60); // 计算分钟数
        if($minutes > 0){
            $pay_str .= sprintf("%s分",$minutes);
        }
        $seconds = $timeDiff % 60; // 计算秒数
        if($seconds > 0){
            $pay_str .= sprintf("%s秒",$seconds);
        }
        $today = date("Ymd",time());
        $door_time = strtotime($info["end_door_time"]) - time();
        if($door_time <= 60*30){
            $info->door_str = "30分钟之内";
        }else if($door_time <= 60*60*2){
            $info->door_str = "2小时之内";
        }else{
            $door_date = date("Ymd",strtotime($info["end_door_time"]));
            $door_time = explode(" ",$info["start_door_time"])[1]."~".explode(" ",$info["end_door_time"])[1];
            if($today == $door_date){
                $info->door_str = "今天:".$door_time;
            }else if($door_date == date("Ymd",strtotime("+1 day"))){
                $info->door_str = "明天:".$door_time;
            }else if($door_date == date("Ymd",strtotime("+2 day"))){
                $info->door_str = "后天:".$door_time;
            }
        }
        $info->pay_str=  $pay_str;
        $info->express_user = (new Express())->express_user_info(null,$info->express_uid);

        #订单快递员评价
        $is_comment = ExpressComment::where("order_id",$info["oid"])->find();
        $info->is_comment = $is_comment?1:0;
        $info->comment_info = $is_comment;
        return $info;
    }

}